<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2018/8/27
 * Time: 17:42
 */
namespace app\wechat\controller;
use think\Controller;

class Base extends Controller {
    /**
     * @var mixed 请求参数
     */
    protected $params;

    /**
     * @var 配置文件
     */
    protected $config;

    /**
     * @var mixed 用户id
     */
    protected $id;

    /**
     * @var string 用户唯一标识openid
     */
    protected $openid;

    /**
     * @var string 会话密钥session_key
     */
    protected $session_key;

    /**
     * @var string 小程序唯一标识
     */
    protected $app_id;

    /**
     * @var string 小程序的 app secret
     */
    protected $app_secret;

    /**
     * @var array 用户敏感信息
     */
    protected $info;

    /**
     * @var bool 登录验证，true开启，false关闭
     */
    protected $needLogin = true;

    /**
     * 从一个难以访问的属性读取数据的时候(1.无访问权限2.未初始化) __get() 方法被调用
     * @param $name  属性名
     * @return mixed|\think\db\Query
     */
    public function __get($name){
        return $this->$name = \think\Db::name($name);
    }

    public function __construct(){
        parent::__construct();
        $this->params = input('param.');
        $config = get_config();
        $this->app_id = $config['app_id'];
        $this->app_secret = $config['app_secret'];

        if ( $this->needLogin ) {
            if ( empty($this->params['token']) ) {
                return error(-1, '参数错误');
            }
            $this->id = \think\Cache::get($this->params['token']);
            if ( !$this->id ) {
                return error(-1, 'token失效');
            }
        }
    }

    /**
     * 获取openid和session_key
     * 请求成功返回的JSON数据包 {"openid": "OPENID","session_key": "SESSIONKEY"}
     * 请求错误时返回JSON数据包(示例为Code无效) {"errcode": 40029,"errmsg": "invalid code"}
     * @throws \Exception
     */
    protected function _getOpenidSessionKey(){
        $url = "https://api.weixin.qq.com/sns/jscode2session?appid={$this->app_id}&secret={$this->app_secret}&js_code={$this->params['code']}&grant_type=authorization_code";
        $res = \Http::get($url);
        $res = json_decode($res, true);
        if ( isset($res['errcode']) ) {
            throw new \Exception($res['errmsg'], $res['errcode']);
        }
        $this->openid = $res['openid'];
        $this->session_key = $res['session_key'];
    }

    /**
     * 保存登录信息
     * @throws \Exception
     */
    protected function _saveLoginInfo(){
        $data = [
            'nickname'    => $this->info['nickName'],
            'gender'      => $this->info['gender'],
            'country'     => $this->info['country'],
            'province'    => $this->info['province'],
            'city'        => $this->info['city'],
            'avatar'      => $this->info['avatarUrl'],
        ];
        $info = $this->wx_user->where(['openid'=>$this->openid])->find();
        if ( empty($info) ) {
            $data = array_merge($data,[
                'openid'      => $this->openid,
                'session_key' => $this->session_key,
                'create_time' => time()
            ]);
            $row = $this->wx_user->insertGetId($data);
            $uid = $row;
        } else {
            $data = array_merge($data,[
                'session_key' => $this->session_key,
                'update_time' => time()
            ]);
            $row = $this->wx_user->where(['openid'=>$this->openid])->update($data);
            $uid = $info['id'];
        }
        if ( !$row ) {
            throw new \Exception('保存用户信息失败', -1);
        }
        $this->token = md5($this->openid);
        $rs = \think\Cache::set($this->token, $uid, 3600 * 24 * 7);
        if ( !$rs ) {
            throw new \Exception('保存用户信息失败', -1);
        }
    }

    /**
     * 签名验证
     * @throws \Exception
     */
    protected function _checkSession(){
        $signature = sha1( $this->params['rawData'].$this->session_key );
        if ( $this->params['signature'] != $signature ) {
            throw new \Exception('数字签名失败', -1);
        }
    }

    /**
     * 用户信息解密
     * @throws \Exception
     */
    protected function _getDecryptInfo(){
        $pc = new \WxBizDataCrypt( $this->app_id, $this->session_key );
        $pc->decryptData( $this->params['encryptedData'], $this->params['iv'], $this->info );
    }

    /**
     * 保存用户信息
     */
    protected function _saveUserInfo(){
        $this->wx_user->update([
            'id'       => $this->id,
            'nickname' => $this->info['nickName'],
            'gender'   => $this->info['gender'],
            'country'  => $this->info['country'],
            'province' => $this->info['province'],
            'city'     => $this->info['city'],
            'avatar'   => $this->info['avatarUrl'],
            'update_time' => time(),
        ]);
    }
}